#ifndef _SDB_PAGER_H_
#define _SDB_PAGER_H_

/*
 * Spinneret - Semi-Structured Database Engine
 * Copyright (c) 2009 Tom Bradford <spinneretdb.org>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

/**
 * Pager services paging requests on behalf of higher level data structures
 * such as B+Trees and Hash Tables.  Its primary purpose is to read, write,
 * and delete pages stored by a secondary storage system.  It also provides
 * hooks into the Transaction Log system.
 */

#include <stdio.h>
#include "main/common.h"
#include "utils/mem.h"

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus


/* Possible Pager types */
typedef enum {
    fspager
} sdb_pager_type_t;

/* Forward declarations */
typedef struct sdb_pager_t sdb_pager_t;
typedef struct sdb_pager_functions_t sdb_pager_functions_t;

/** Abstract type for Pager instances */
struct sdb_pager_t {
    sdb_pager_functions_t* functions;
    sdb_size_t pageSize;
};

/** Implementation type for Pager Information instances */
typedef struct {
    bool exists;          // If 'false', the rest of this info is invalid
    sdb_size_t blockSize; // Optimal block size for the underlying file (or -1)
    sdb_off_t fileSize;   // Size of the file in bytes
} sdb_pager_info_t;

/** Implementation type for Pager Function Table instances */
struct sdb_pager_functions_t {
    /** Control Functions */
    sdb_status_t (*openFunction)(sdb_pager_t* file);
    sdb_status_t (*createFunction)(sdb_pager_t* file);
    sdb_status_t (*closeFunction)(sdb_pager_t* file);
    sdb_status_t (*unlinkFunction)(sdb_pager_t* file);

    /*  Informational Function */
    sdb_status_t (*infoFunction)(sdb_pager_t* file, sdb_pager_info_t* info);

    /* I/O Functions */
    sdb_status_t (*readFunction)(sdb_pager_t* file, sdb_off_t pos,
                                 char* buffer, sdb_size_t len);
    sdb_status_t (*writeFunction)(sdb_pager_t* file, sdb_off_t pos,
                                  char* buffer, sdb_size_t len);
};

/** Create a Pager instance */
sdb_pager_t* sdb_pager_new(sdb_mem_t* mem);

/** Initialize a Pager instance */
sdb_pager_t* sdb_pager_init(sdb_pager_t* pager,
                            sdb_pager_functions_t* functions);


#ifdef __cplusplus
}
#endif // __cplusplus

#endif // _SDB_PAGER_H_
